﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using YKXiangQi.Enums;
using YKXiangQi.Models;

namespace YKXiangQi.Common
{
    public static class ExtensionMethod
    {
        public static bool IsLowerCase(this string str)
        {
            return str.ToLower() == str;
        }

        public static int ToInt32(this string str)
        {
            int result;
            return Int32.TryParse(str, out result) ? result : 0;
        }

        public static int ToInt32(this char chr)
        {
            return chr.ToString().ToInt32();
        }

        public static double ToDouble(this string str)
        {
            double result;
            if (Double.TryParse(str, out result))
                return result;

            throw new InvalidDataException();
        }

        public static long ToLong(this object obj)
        {
            long result;
            if (long.TryParse(obj.ToString(), out result))
                return result;

            throw new InvalidDataException();
        }

        public static T DeepClone<T>(this T obj)
        {
            using (var memStream = new MemoryStream())
            {
                var binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memStream, obj);
                memStream.Seek(0, SeekOrigin.Begin);

                return (T)binaryFormatter.Deserialize(memStream);
            }
        }

        public static byte[] Serialize<T>(this T obj)
        {
            using (var memStream = new MemoryStream())
            {
                var binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memStream, obj);
                memStream.Position = 0;
                var buffer = new byte[memStream.Length];
                memStream.Read(buffer, 0, buffer.Length);

                return buffer;
            }
        }

        public static T Deserialize<T>(this byte[] obj)
        {
            using (var memStream = new MemoryStream(obj))
            {
                var binaryFormatter = new BinaryFormatter();
                return (T) binaryFormatter.Deserialize(memStream);
            }
        }

        public static string ToBase64(this byte[] obj)
        {
            return Convert.ToBase64String(obj);
        }

        public static byte[] ToArray(this string obj)
        {
            return Convert.FromBase64String(obj);
        }

        public static Point GetFromPosition(this string notation)
        {
            var xPos = new List<char>() { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };

            return new Point()
                       {
                           X = xPos.IndexOf(notation[0]),
                           Y = 9 - notation[1].ToInt32()
                       };
        }

        public static Point GetToPosition(this string notation)
        {
            var xPos = new List<char>() { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
            return new Point()
                       {
                           X = xPos.IndexOf(notation[2]),
                           Y = 9 - notation[3].ToInt32()
                       };
        }

        public static string GetEnumDescription<T>(this T @enum)
        {
            var enumType = typeof(T);
            var field = enumType.GetField(@enum.ToString());
            var attribute = Attribute.GetCustomAttribute(field, typeof (DescriptionAttribute)) as DescriptionAttribute;
            if (attribute == null) return string.Empty;

            return attribute.Description;
        }
    }
}
